package bloggo

import (
	"bloggo/structs"
	"context"
	"fmt"
	"gitee.com/chunanyong/zorm"
	"golang.org/x/crypto/bcrypt"
	"math/rand"
	"strconv"
	"time"
)

const (
	//登录类型
	//邮箱登录
	EMAIL = 1
	//扣扣登录
	QQ = 2

	// DEFAULT_NICKNAME 默认用户昵称
	DEFAULT_NICKNAME = "用户"

	// DEFAULT_AVATAR 默认用户头像
	DEFAULT_AVATAR = "https://xiaomy.xyz/static/avatar/user.png"
)

var (
	// ADMIN 管理员
	ADMIN = RoleLabel{1, "管理员", "admin"}

	// USER 普通用户
	USER = RoleLabel{2, "用户", "user"}

	// TEST 测试账号
	TEST = RoleLabel{3, "测试", "test"}
)

type RoleLabel struct {
	RoldId int    `json:"roldId"`
	Name   string `json:"name"`
	Label  string `json:"label"`
}

// SendMailCode 发送邮箱验证码
func SendMailCode(emails ...string) bool {
	if len(emails) <= 0 {
		return false
	}
	rand.Seed(time.Now().UnixNano())
	code := rand.Intn(8999) + 1000 //生成1000-9999之间的随机数
	go func() {
		err := SendPlainMail("验证码", fmt.Sprint("您的验证码为 ", code, " 有效期15分钟，请不要告诉他人哦！"), emails)
		if err != nil {
			Log(err.Error())
		}
	}()
	// 将验证码存入redis，设置过期时间为15分钟
	for i := range emails {
		Setex(USER_CODE_KEY+emails[i], []byte(strconv.Itoa(code)), CODE_EXPIRE_TIME)
	}
	return true
}

// CheckCode 检查验证码
func CheckCode(username, code string) *R {
	if len(username) <= 0 || len(code) <= 0 {
		return Fail()
	}
	get, err := Get(USER_CODE_KEY + username)
	if err != nil {
		return Fail()
	}
	if code != string(get) {
		return FailMessage("验证码错误！")
	}
	Del(USER_CODE_KEY + username)

	finder := zorm.NewFinder().Append("SELECT id FROM").Append(structs.TbUserAuthStructTableName)
	finder.Append("WHERE username=? LIMIT 1", username)
	var id int
	has, err := zorm.QueryRow(context.Background(), finder, &id)
	if has && err == nil && id != 0 {
		return FailMessage("账号已被注册!")
	}
	return Ok()
}

// Register 注册
var Register = func(username, password, code string, registerType int8) *R {
	// 校验账号是否合法
	checkCode := CheckCode(username, code)
	if checkCode.Code != 2000 {
		return checkCode
	}
	userId, err := zorm.Transaction(context.Background(), func(ctx context.Context) (interface{}, error) {
		// 新增用户信息
		userInfo := structs.TbUserInfoStruct{}
		userInfo.Email = ""
		userInfo.Nickname = fmt.Sprint(DEFAULT_NICKNAME, time.Now().UnixMilli())
		userInfo.Avatar = DEFAULT_AVATAR
		userInfo.CreateTime = time.Now()
		userInfo.UpdateTime = time.Now()
		_, err := zorm.Insert(ctx, &userInfo)
		if err != nil {
			return nil, err
		}

		// 绑定用户角色
		userRole := structs.TbUserRoleStruct{}
		userRole.UserId = userInfo.Id
		userRole.RoleId = USER.RoldId
		_, err = zorm.Insert(ctx, &userRole)
		if err != nil {
			return nil, err
		}

		// 新增用户账号
		userAuth := structs.TbUserAuthStruct{}
		userAuth.UserInfoId = userInfo.Id
		userAuth.Username = username
		fromPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
		if err != nil {
			return nil, err
		}
		userAuth.Password = string(fromPassword)
		userAuth.LoginType = registerType
		userAuth.CreateTime = time.Now()
		userAuth.UpdateTime = time.Now()
		userAuth.LastLoginTime = time.Now()
		_, err = zorm.Insert(ctx, &userAuth)
		if err != nil {
			return nil, err
		}
		return userInfo.Id, nil
	})
	if err != nil {
		return FailMessage(err.Error())
	}
	return OkData(userId)
}
